<template>
    <div class="editor">
        <Toolbar
            style="border-bottom: 1px solid #EEEEEE"
            :style="toolbarStyle"
            :editor="editorRef"
            :defaultConfig="_toolbarConfig"
            :mode="mode"
        />
        <Editor
            style="height: 500px; overflow-y: hidden;"
            :style="editorStyle"
            :model-value="valueHtml"
            @update:modelValue="handleSyncValue"
            :defaultConfig="_editorConfig"
            :mode="mode"
            @onCreated="handleCreated"
        />
    </div>
</template>
<script lang="ts" setup>
import { uploadFile } from '@/api/upload';
import { type IDomEditor, type IEditorConfig, type IToolbarConfig } from '@wangeditor/editor';
import { Editor, Toolbar } from '@wangeditor/editor-for-vue';
import '@wangeditor/editor/dist/css/style.css';
import type { StyleValue } from 'vue';
import type { Exposed } from './type';

/**
 * @param {string} url 图片 src ，必须
 * @param {string} alt 图片描述文字，非必须
 * @param {string} href 图片的链接，非必须
 */
type InsertFnType = (url: string, alt?: string, href?: string) => void
defineOptions({
    name: "GpEditor",
    inheritAttrs: true
})
const { mode = 'simple', toolbarConfig, editorConfig } = defineProps<{
    toolbarStyle?: StyleValue
    editorStyle?: StyleValue
    mode?: 'default' | 'simple'
    toolbarConfig?: Partial<IToolbarConfig>
    editorConfig?: Partial<IEditorConfig>
}>()
defineExpose<Exposed>({
    editor() {
        return editorRef.value
    },
})
const emit = defineEmits<{
    onCreated:[instance: IDomEditor]
}>()
const editorRef = shallowRef<IDomEditor>()
const valueHtml = defineModel<string>()
const handleSyncValue = (e: any) => {
    valueHtml.value = e
}
const defToolbarConfig: Partial<IToolbarConfig> = {
    toolbarKeys: [
        "bold",
        "underline",
        "italic",
        "through",
        "color",
        "bgColor",
        "clearStyle",
        "|",
        "emotion",
        "insertLink",
        {
            key: "group-image",
            menuKeys: ["insertImage", "uploadImage"],
            title: "图片",
            iconSvg: `<svg viewBox="0 0 1024 1024"><path d="M959.877 128l0.123 0.123v767.775l-0.123 0.122H64.102l-0.122-0.122V128.123l0.122-0.123h895.775zM960 64H64C28.795 64 0 92.795 0 128v768c0 35.205 28.795 64 64 64h896c35.205 0 64-28.795 64-64V128c0-35.205-28.795-64-64-64zM832 288.01c0 53.023-42.988 96.01-96.01 96.01s-96.01-42.987-96.01-96.01S682.967 192 735.99 192 832 234.988 832 288.01zM896 832H128V704l224.01-384 256 320h64l224.01-192z"></path></svg>`
        },
        "|",
        "undo",
        "redo"
    ]
}
const _toolbarConfig = computed(() => {
    return {
        ...defToolbarConfig,
        ...toolbarConfig
    }
})
const defEditorConfig: Partial<IEditorConfig> = {
    placeholder: '',
    MENU_CONF: {
        uploadImage: {
            async customUpload(file: File, insertFn: InsertFnType) {
                const { fullName, name } = await uploadFile(file)
                insertFn(fullName, name)
            },
        }
    }
}
const _editorConfig = computed(() => {
    return {
        ...defEditorConfig,
        editorConfig
    }
})
onBeforeUnmount(() => {
    const editor = editorRef.value
    if (editor == null) return
    editor.destroy()
})

const handleCreated = (editor: IDomEditor) => {
    editorRef.value = editor
    emit('onCreated', editor)
}
</script>
<style lang="less" scoped>
.editor {
    border: 1px solid #CED4DB;
    :is(h1, h2, h3, h4, h5, h6) {
        font-weight: bold;
    }
    :is(h1) {
        font-size: 2em;
    }
    :is(h2) {
        font-size: 1.5em;
    }
    :is(h3) {
        font-size: 1.17em;
    }
    :is(h4) {
        font-size: 1em;
    }
    :is(h5) {
        font-size: 0.83em;
    }
}
</style>